package cn.caplike.demo.repository.java;

import com.alibaba.fastjson.JSON;
import com.esotericsoftware.kryo.Kryo;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

import java.io.*;

/**
 * Description: 深度拷贝.
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2022-05-16 11:20
 */
@SuppressWarnings("unchecked")
public class DeepCopy {

    public static void main(String[] args) {
        // deepCopyBySerializing();

        // deepCopyByProxy();

        // deepCopyByKryo();

        // deepCopyByJson();


        final String abc1 = String.format("reload-lock:%s", "abc");
        final String abc2 = String.format("reload-lock:%s", "abc");
        System.out.println(abc1.equals(abc2));

        System.out.println(abc1.hashCode());
        System.out.println(abc2.hashCode());
    }

    private static void deepCopyByJson() {
        final A a = new A();
        a.setName("LiKe");
        System.out.println(a);

        final String s = JSON.toJSONString(a);
        final A a1 = JSON.parseObject(s, A.class);

        System.out.println(a1);
        System.out.println(a1.getName());
    }

    private static void deepCopyByKryo() {
        final A a = new A();
        a.setName("LiKe");
        System.out.println(a);

        Kryo kryo = new Kryo();
        kryo.setRegistrationRequired(false);
//        kryo.register(a.getClass());
        final A copy = kryo.copy(a);
        System.out.println(copy);
        System.out.println(copy.getName());

        kryo = null;
    }

    private static void deepCopyByProxy() {
        final A a = new A();
        a.setName("LiKe");
        System.out.println(a);

        final A proxy = getProxy(a);
        System.out.println(proxy);
        System.out.println(proxy.getName());
    }

    private static void deepCopyBySerializing() {
        final A a = new A();
        a.setName("LiKe");
        System.out.println(a);

        final A proxy = getCopy(a);
        System.out.println(proxy);
        System.out.println(proxy.getName());
    }

    private static <Target> Target getProxy(Target target) {
        return
            (Target) Enhancer.create(
                target.getClass(),
                (MethodInterceptor) (proxy, method, args, methodProxy) -> method.invoke(proxy, args)
            );
    }

    private static <Target> Target getCopy(Target target) {
        // TODO 利用对象流深度拷贝对象
        try (
            final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)
        ) {
            objectOutputStream.writeObject(target);

            try (
                final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                final ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)
            ) {
                return (Target) objectInputStream.readObject();
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 必须实现 Serializable 接口.
     */
    public static /*final*/ class A {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
